#ifndef _drew_smooth_rel_
#define _drew_smooth_rel_

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include <gmp.h>
#include <unistd.h>
#include <sys/types.h>
#include "mpzqform.h"
#include "mpzsmoothscan.h"

/*
    Copyright 2009-2010 Andrew V. Sutherland

    This file is part of "smoothrelation".

    smoothrelation is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    smoothrelation is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with smalljac.  If not, see <http://www.gnu.org/licenses/>.
*/


#define TEST_TIMING		0				// set to 1 to time form composition and smoothness testing spped

#define LOG2			0.69314718055994530941723212145818
#define log2_Drew(x)		(log(x)/LOG2)
#define delta_msecs(s,t)	((t-s)/(CLOCKS_PER_SEC/1000))		// assumes CLOCKS_PER_SEC is a multiple of 1000

#define MAX_B			50000			// maximum smoothness bound
#define MAX_BASE			5133			// set to pi(MAX_B), this is overkill
#define MAX_EBITS			(MAX_B/2)		// total across all exponents
#define MAX_K0			4
#define MAX_RELATIONS		1				// maximum number of distinct relations to remember
#define BATCH_SIZE		2048
#define LOG2_BATCH_SIZE	12
#define MAX_EXP_BITS		16
#define OMEGA			1.25				// 1.6

/*
	The arrays below are statically allocated to keep them off the stack.
	These could easily be allocated dynamically.
*/
unsigned short r[MAX_RELATIONS][MAX_BASE];
mpz_t ga[MAX_EBITS], gb[MAX_EBITS];
int bitmap[MAX_EBITS];						// index of ell corresponding to each exp bit
char beta_e[MAX_EBITS];					// exponent bit-vector for the current beta
double wts[MAX_EBITS];						// binary logarithmic weight of each bit
mpz_t a[MAX_BASE],b[MAX_BASE];
unsigned long ell[2*MAX_BASE], ell0[MAX_BASE];
unsigned long h[MAX_BASE];
char hs[MAX_BASE];
int eoff[MAX_BASE], ebits[MAX_BASE];

struct exp_struct {
	unsigned char i[4];
	unsigned short e[4];
};

void smoothbox_init (mpz_t D, int B , int unramified);
int smoothbox_feed (mpz_t out_a, mpz_t out_b, struct exp_struct out_exp[1], mpz_t a, mpz_t b, struct exp_struct in_exp[1]);
int smoothbox_flush (mpz_t out, mpz_t out_b, struct exp_struct out_exp[1]);
int test_drew ( int argc, char *argv[] , unsigned long input_seed);



/*
	smoothbox should eventually be put into its own module
*/

#define SB_BS				4096		// smooth test batch size
#define SB_NSP			7			// number of small primes for early abort
#define SB_MIN_WT			(1.2*SB_NSP)	// threshhold for early abort

static mpz_t sb_P;
static mpz_t *sb_a, *sb_b, *sb_t;
static int sb_n, sb_nsp;
static int sb_sp[SB_NSP+1];
static double sb_spw[SB_NSP+1];
static struct exp_struct *sb_exp;


#endif
